<?php
declare (strict_types = 1);

namespace app\controller\backend;

use app\BaseController;
use app\exception\InstallException;
use app\model\Admin;
use app\model\Model;
use app\model\Route;
use app\model\Website;
use app\model\WebsiteLang;
use app\model\WebsiteServer;
use app\model\WebsiteSetting;
use app\service\ThemeService;
use think\facade\Db;
use think\facade\View;

class SystemInstallController extends BaseController
{
    /**
     * 显示资源列表
     *
     */
    public function index()
    {
        if(hcInstalled()){
            return redirect('/admin.php');
        }
        $year = date('Y',time());
        $month = date('m',time());
        $day = date('d',time());
        View::assign(['year'=>$year,'month'=>$month,'day'=>$day]);
        return View::fetch(CMS_ROOT.'data/install/install.html');
    }

    public function monitor(): string
    {
        //        if (file_exists_case('data/conf/config.php')) {
//            @unlink('data/conf/config.php');
//        }
        $data               = [];
        $data['phpversion'] = @phpversion();
        $data['os']         = PHP_OS;
        $tmp                = function_exists('gd_info') ? gd_info() : [];
//        $server             = $_SERVER["SERVER_SOFTWARE"];
//        $host               = $this->request->host();
//        $name               = $_SERVER["SERVER_NAME"];
//        $max_execution_time = ini_get('max_execution_time');
//        $allow_reference    = (ini_get('allow_call_time_pass_reference') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>');
//        $allow_url_fopen    = (ini_get('allow_url_fopen') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>');
//        $safe_mode          = (ini_get('safe_mode') ? '<font color=red>[×]On</font>' : '<font color=green>[√]Off</font>');
        $err = 0;
        if (empty($tmp['GD Version'])) {
            $gd = '/static/install/image/success_icon.jpg';
            $err++;
        } else {
            $gd = '/static/install/image/error_icon.png ' . $tmp['GD Version'];
        }

        if (class_exists('pdo')) {
            $data['pdo'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['pdo'] = '/static/install/image/error_icon.png';
            $err++;
        }

        if (extension_loaded('pdo_mysql')) {
            $data['pdo_mysql'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['pdo_mysql'] = '/static/install/image/error_icon.png';
            $err++;
        }

        if (extension_loaded('curl')) {
            $data['curl'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['curl'] = '/static/install/image/error_icon.png';
            $err++;
        }

        if (extension_loaded('gd')) {
            $data['gd'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['gd'] = '/static/install/image/error_icon.png';
            if (function_exists('imagettftext')) {
                $data['gd'] .= '/static/install/image/error_icon.png';
            }
            $err++;
        }

        if (extension_loaded('mbstring')) {
            $data['mbstring'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['mbstring'] = '/static/install/image/error_icon.png';
            if (function_exists('imagettftext')) {
                $data['mbstring'] .= '/static/install/image/error_icon.png';
            }
            $err++;
        }

        if (extension_loaded('fileinfo')) {
            $data['fileinfo'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['fileinfo'] = '/static/install/image/error_icon.png';
            $err++;
        }

        if (ini_get('file_uploads')) {
            $data['upload_size'] = ini_get('upload_max_filesize') ;
        } else {
            $data['upload_size'] = '未开启';
            $err++;
        }

        if (function_exists('session_start')) {
            $data['session'] = '/static/install/image/success_icon.jpg';
        } else {
            $data['session'] = '/static/install/image/error_icon.png';
            $err++;
        }

        if (version_compare(phpversion(), '7.2.0', '>=') && version_compare(phpversion(), '7.0.0', '<') && ini_get('always_populate_raw_post_data') != -1) {
            $data['always_populate_raw_post_data']          = '未关闭';
            $data['show_always_populate_raw_post_data_tip'] = true;
            $err++;
        } else {
            $data['always_populate_raw_post_data'] = '已关闭';
        }

        $folders    = [
            realpath(CMS_ROOT . 'data') . DIRECTORY_SEPARATOR,
            realpath(CMS_ROOT .'public/themes') . DIRECTORY_SEPARATOR,
            realpath(CMS_ROOT.'view/website') . DIRECTORY_SEPARATOR,
            realpath(CMS_ROOT.'runtime') . DIRECTORY_SEPARATOR,
        ];
        $newFolders = [];
        foreach ($folders as $dir) {
            $testDir = $dir;
            sp_dir_create($testDir);
            if (sp_testwrite($testDir)) {
                $newFolders[$dir]['w'] = true;
            } else {
                $newFolders[$dir]['w'] = false;
                $err++;
            }
            if (is_readable($testDir)) {
                $newFolders[$dir]['r'] = true;
            } else {
                $newFolders[$dir]['r'] = false;
                $err++;
            }
            if($newFolders[$dir]['w'] && $newFolders[$dir]['r']){
                $newFolders[$dir]['icon'] = '/static/install/image/success_icon.jpg';
            }else{
                $newFolders[$dir]['icon'] =  '/static/install/image/error_icon.png';

            }
        }
        $data['err'] = $err;
        $data['folders'] = $newFolders;
        View::assign($data);
        return View::fetch(CMS_ROOT.'data/install/monitor.html');
    }

    public function configure(): string
    {
        return View::fetch(CMS_ROOT.'data/install/configure.html');
    }

    public function create(): string
    {
        $param = request()->param();
        if(empty($param['username'])){
            $param['username'] = 'admin@admin.com';
        }
        if(empty($param['password'])){
            $param['password'] = 'huocms.com';
        }
        $dbConfig = [
            'type' => 'mysql',
            // 连接名
            'hostname' => $param['hostname'],
            // 用户名
            'username'        => $param['username'],
            // 密码
            'password'        => $param['password'],
            // 端口
            'hostport'        => $param['hostport'],
            // 数据库编码默认采用utf8mb4
            'charset'         => $param['charset'],
            // 数据库表前缀
            'prefix'          => $param['prefix'],
        ];
        $this->updateDbConfig($dbConfig);
        $sql    = "CREATE DATABASE IF NOT EXISTS `{$param['database']}` DEFAULT CHARACTER SET " . $param['charset'];
        $db     = Db::connect('install_db');
        $db->execute($sql);
        $dbConfig['database'] = $param['database'];
        $this->exchangeEnv($dbConfig);
        session('install.db_config', $dbConfig);
        $sql  = hcSplitSql(CMS_ROOT . '/data/install/install.sql', $dbConfig['prefix'], $dbConfig['charset']);
        session('install.sql', $sql);
        View::assign('sql_count', count($sql));
        session('install.error', 0);
        session('install.admin_info', [
            'name' => $param['admin'],
            'account'  => $param['email'],
            'password' => makePassword($param['admin_pass'])
        ]);
        return View::fetch(CMS_ROOT.'data/install/create.html');
    }

    public function install()
    {
        $dbConfig = session('install.db_config');
        $sql      = session('install.sql');

        if (empty($dbConfig) || empty($sql)) {
            return json([
                'code' => -1,
                'data' => '',
                'msg' => '非法安装!'
            ]);
        }

        $sqlIndex = $this->request->param('sql_index', 0, 'intval');

        $this->updateDbConfig($dbConfig);
        $db = Db::connect('install_db');

        if ($sqlIndex >= count($sql)) {
            return json([
                'code' => 200,
                'data' => '',
                'msg' => '安装完成!'
            ]);
        }

        $sqlToExec = $sql[$sqlIndex] . ';';

        $result = sp_execute_sql($db, $sqlToExec);

        if (!empty($result['error'])) {
            return json([
                'code' => -1,
                'data' => [
                    'sql'       => $sqlToExec,
                    'exception' => $result['exception']
                ],
                'msg' => '安装失败!'
            ]);
        } else {
            return json([
                'code' => 0,
                'data' => $result,
                'msg' => '安装成功!'
            ]);
        }
    }

    public function exchangeEnv($dbConfig)
    {
        $envFile = CMS_ROOT . '.env';
        $example = CMS_ROOT.'.example.env';

        if(file_exists($example)){
            copy($example,$envFile);
        }else{
            touch($envFile);
            $initArray = [
                "APP_DEBUG = true",
                "APP_HOST = http://localhost",
                "",
                "[APP]",
                "DEFAULT_TIMEZONE = Asia/Shanghai",
                "",
                "[DATABASE]",
                "TYPE = mysql",
                "HOSTNAME = 127.0.0.1",
                "DATABASE = huo_cms",
                "USERNAME = root",
                "PASSWORD = ",
                "HOSTPORT = 3306",
                "CHARSET = utf8mb4",
                "DEBUG = true",
                "PREFIX = hc_",
                "",
                "[LANG]",
                "default_lang = zh-cn",    
            ];
            file_put_contents($envFile,implode('', $initArray));
        }
        
        $merge = [
            'app_debug' => true,
            'app_host' => request()->domain(),
        ];
        $data = [];
        foreach(array_merge($merge,$dbConfig) as $key => $val){
            $key = strtoupper($key);
            $data[$key] = $val;
        }
        
        $this->updateEnv($envFile,$data);
    }

    public function updateEnv($envFile,$data = array())
    {
        $oldEnv = file($envFile);
        if (! count($data)) {return;}
        if (array_keys($data) === range(0, count($data) - 1)) {return;}
        $pattern = '/([^\=]*)\=[^\n]*/';
        $newEnv = [];
        foreach ($oldEnv as $line) {
            preg_match($pattern, $line, $matches);

            if (!count($matches)) {
                $newEnv[] = $line;
                continue;
            }

            if (!key_exists(trim($matches[1]), $data)) {
                $newEnv[] = $line;
                continue;
            }

            $line = trim($matches[1]) . "={$data[trim($matches[1])]}\n";
            $newEnv[] = $line;
        }
        $newContent = implode('', $newEnv);

        file_put_contents($envFile, $newContent);
    }

    public function testPass(): \think\response\Json
    {
        $param = request()->param();
        $dbConfig = [
            'type' => 'mysql',
            // 连接名
            'hostname'        => $param['hostname'],
            // 数据库名
            'username'        => $param['username'],
            // 密码
            'password'        => $param['password'],
            // 端口
            'hostport'        => $param['hostport'],
        ];
        $this->updateDbConfig($dbConfig);
        $supportInnoDb = false;
        try {
            $db     = Db::connect('install_db');
            $engines = $db->query("SHOW ENGINES;");
            foreach ($engines as $engine) {
                if ($engine['Engine'] == 'InnoDB' && $engine['Support'] != 'NO') {
                    $supportInnoDb = true;
                    break;
                }
            }
        } catch (\Exception $e) {
            return jsonReturn(-1,'数据库账号或密码不正确！' . $e->getMessage());
        }
        if (!$supportInnoDb) {
            return jsonReturn(-2,'数据库账号密码验证通过，但不支持InnoDb!');
        }else{
            return jsonReturn(0,'success');
        }
    }

    public function installCompleteCheck(): \think\response\Json
    {

        $admin = session("install.admin_info");
        if(empty($admin)){
            return jsonReturn(-1,'用户创建失败，请重试');
        }
        Db::startTrans();
        try {
            // 创建管理员
            $Admin = new Admin();
            $admin['seller_id'] = 1 ;
            $admin['status'] = 1 ;
            $admin['group'] = 1;
            $res = $Admin->addAdmin($admin)['data'];
            $res->role()->attach(1,['seller_id'=>1]);
            $website = new Website();
            $siteParam = [
                'title' => '演示站点',
                'domain' => request()->host()
            ];
            // 创建站点
            // 1. 保存站点到数据库
            $res = $website -> addWebsite($siteParam);
            if($res['data'] != 1){
                throw new InstallException();
            }
            // 2. 生成一份默认的站点配置，配置的值为空
            $tmpData = [
                "site_name"=>"",
                "seo_title"=>"",
                "seo_keywords"=>"",
                "seo_description"=>"",
                "icp"=>"",
                "gwa"=>"",
                "admin_email"=>"",
                "analytics_code"=>"",
                "author"=>"派流",
                "icp_link"=>"https://beian.miit.gov.cn/#/Integrated/index",
                "logo"=>"",
                "customer_code" => "",
                "gwa_link" => "http://www.beian.gov.cn/portal/index.do",
            ];
            $sysData = [
                "setting"=> json_encode($tmpData),
                "website_id"=>$res['data'],
                "lang"=>"zh"
            ];
            $siteSetting = new WebsiteSetting();
            $siteSetting -> addWebsiteSetting($sysData);
            // 3. 选择站点语言简体中文，服务器为本地服务器
            $langData[]= [
                'seller_id' => 1,
                'website_id'    => $res['data'],
                'lang_name' => '简体中文',
                'lang' => 'zh',
            ];
            $WebsiteLang = new WebsiteLang();
            $WebsiteLang->addWebsiteLang($langData);
            $serverData = [
                'seller_id' => 1,
                'website_id'    => $res['data'],
                'type'  => 1,
            ];
            $WebsiteServer = new WebsiteServer();
            $WebsiteServer->addWebsiteServer($serverData);
            // 4.生成路由
            $Route = new Route();
            $Route->updateRoute(['seller_id'=>1],['website_id'=>$res['data']]);
            $Route->getRoutes($res['data'],1,'zh');
            // 5.安装模版
            $ThemeService = new ThemeService();
            $ThemeService->installTheme('demo',$res['data'],1);

            @touch(CMS_ROOT . 'data/install.lock');
            session("install.step",4);
            Db::commit();
        } catch(InstallException $e){
            @unlink(CMS_ROOT . 'data/install.lock');
            Db::rollback();
            return jsonReturn(-3,'安装失败,请清空数据库后重试');
        }catch (\Exception $e) {
            @unlink(CMS_ROOT . 'data/install.lock');
            Db::rollback();
            return jsonReturn(-1,'用户创建失败，请重试'.$e->getMessage());
        }
        return jsonReturn(0,'success');
    }

    public function completeCheck(): \think\response\Json
    {
        if(session("install.step") == 4){
//            @touch(CMS_ROOT . 'data/install.lock');
            return jsonReturn(0,'安装成功');
        }else{
            return jsonReturn(-1,'安装失败');
        }
    }

    public function complete(): string
    {
        return View::fetch(CMS_ROOT.'data/install/complete.html');
    }
    private function updateDbConfig($dbConfig)
    {
        $oldDbConfig                              = config('database');
        $oldDbConfig['connections']['install_db'] = $dbConfig;
        config($oldDbConfig, 'database');
    }

    public function write_ini_file($assoc_arr, $path, $has_sections=FALSE): bool
    {
            $content = "";
            if ($has_sections) {
                foreach ($assoc_arr as $key=>$elem) {
                    $content .= "[".$key."]n";
                    foreach ($elem as $key2=>$elem2) {
                        if(is_array($elem2)) {
                            for($i=0;$i<count($elem2);$i++)
                            {
                                $content .= $key2."[] = ".$elem2[$i]."\r\n";
                            }
                        } else if($elem2=="") {
                            $content .= $key2." = n";
                        } else {
                            $content .= $key2." = ".$elem2."\r\n";
                        }
                    }
                }
            } else {
                foreach ($assoc_arr as $key=>$elem) {
                    if(is_array($elem)) {
                        for($i=0;$i<count($elem);$i++) {
                            $content .= $key ."[] = ".$elem[$i]."\r\n";
                        }
                    } else if($elem=="") {
                        $content .= $key." = n";
                    } else {
                        $content .= $key." = ".$elem."\r\n";
                    }
                }
            }
            if (!$handle = fopen($path, 'w')) {
                return false;
            }
            if (!fwrite($handle, $content)) {
                return false;
            }
            fclose($handle);
            return true;
        }
}
